/**
 * 本质上就是问去掉所有可以在最短路上的边，原图是否仍然连通
 */
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;

using llt = long long;
using pil = pair<int, llt>;

struct uf_t{
vector<int> father;
void init(int n){father.assign(n + 1, 0);for(int i=1;i<=n;++i)father[i]=i;}
int find(int x){return x == father[x] ? x : father[x] = find(father[x]);}
void unite(int x, int y){father[find(y)] = find(x);}
};

struct edge_t{
	int from;
	int to;
	int w;
};

llt const INF = 0x7F8F9FAFBFCFDFEF;

vector<edge_t> Edges;
vector<vector<int>> G;

int N, M;

vector<llt> D, U;
vector<int> Flag;

__gnu_pbds::priority_queue<pil, function<bool(const pil &, const pil &)>> Q([](const pil & a, const pil & b){
	if(a.second != b.second) return a.second > b.second;
	return a.first > b.first;
});

void Dij(int s, vector<llt> & d){
    Q.clear();
	d.assign(N + 1, INF);
	Flag.assign(N + 1, 0);

	Q.push({s, d[s] = 0LL});
	while(1){
		while(not Q.empty() and Flag[Q.top().first]) Q.pop();
		if(Q.empty()) break;

		auto h = Q.top();Q.pop();
		Flag[h.first] = 1;

		int v; llt tmp;
		for(auto i : G[h.first]){
			const auto & e = Edges[i];            
			if(Flag[v = e.from ^ h.first ^ e.to]) continue;
			if(d[v] <= (tmp = h.second + e.w)) continue;

			Q.push({v, d[v] = tmp});
		}
	}
	return;
}

uf_t UF;

bool proc(){
	Dij(1, D);
    if(INF == D[N]) return false;

    Dij(N, U);

    auto dis = D[N];
	assert(dis == U[1]);

	UF.init(N);
	for(int i=0;i<M;++i){
		const auto & e = Edges[i];
		if(D[e.from] + e.w + U[e.to] == dis or U[e.from] + e.w + D[e.to] == dis){

		}else{
            UF.unite(e.from, e.to);
		}
	}

	for(int i=2;i<=N;++i){
		if(UF.find(1) != UF.find(i)) return false;
	}
	return true;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int nofkase = 1;
	// cin >> nofkase;
	while(nofkase--){	
		cin >> N >> M;
		G.assign(N + 1, {});
		Edges.reserve(M);

		for(int a,b,c,i=0;i<M;++i){
			cin >> a >> b >> c;
			G[a].emplace_back(Edges.size());
			G[b].emplace_back(Edges.size());
			Edges.push_back({a, b, c});
		}			

		cout << (proc() ? "YES\n" : "NO\n");
	}
    return 0;
}